﻿using System.Text.RegularExpressions;
using System.Net;
using System.Reflection;
using Framework.Common.Reflection;
using Framework.Common;

namespace System.Web
{
    /// <summary>
    /// request 扩展
    /// </summary>
    public static class RequestExtention
    {
        #region 客户端信息
        /// <summary>
        /// 判断当前页面是否接收到了Post请求
        /// </summary>
        /// <returns>是否接收到了Post请求</returns>
        public static bool IsPost(this HttpRequest request)
        {
            return request.HttpMethod.Equals("POST");
        }

        /// <summary>
        /// 判断当前页面是否接收到了Get请求
        /// </summary>
        /// <returns>是否接收到了Get请求</returns>
        public static bool IsGet(this HttpRequest request)
        {
            return request.HttpMethod.Equals("GET");
        }

        /// <summary>
        /// 返回指定的服务器变量信息
        /// </summary>
        /// <param name="request"></param>
        /// <param name="strName">服务器变量名</param>
        /// <returns>服务器变量信息</returns>
        public static string GetServerString(this HttpRequest request, string strName)
        {
            return request.ServerVariables[strName] ?? string.Empty;
        }

        /// <summary>
        /// 返回上一个页面的地址
        /// </summary>
        /// <returns>上一个页面的地址</returns>
        public static string GetUrlReferrer(this HttpRequest request)
        {
            return request.UrlReferrer == null ? string.Empty : request.UrlReferrer.ToString();
        }

        /// <summary>
        /// 得到当前完整主机头
        /// </summary>
        /// <returns></returns>
        public static string GetCurrentFullHost(this HttpRequest request)
        {
            if (!request.Url.IsDefaultPort)
                return string.Format("{0}:{1}", request.Url.Host, request.Url.Port.ToString());
            return request.Url.Host;
        }

        /// <summary>
        /// 得到主机头
        /// </summary>
        /// <returns></returns>
        public static string GetHost(this HttpRequest request)
        {
            return request.Url.Host;
        }


        /// <summary>
        /// 获取当前请求的原始 URL(URL 中域信息之后的部分,包括查询字符串(如果存在))
        /// </summary>
        /// <returns>原始 URL</returns>
        public static string GetRawUrl(this HttpRequest request)
        {
            return request.RawUrl;
        }


        static readonly string[] BrowserName = { "IE", "OPERA", "NETSCAPE", "MOZILLA", "KONQUEROR", "FIREFOX" };

        /// <summary>
        /// 判断当前访问是否来自浏览器软件
        /// </summary>
        /// <returns>当前访问是否来自浏览器软件</returns>
        public static bool IsBrowserGet(this HttpRequest request)
        {
            string curBrowser = request.Browser.Type.ToUpper();
            for (int i = 0; i < BrowserName.Length; i++)
            {
                if (curBrowser.IndexOf(BrowserName[i]) >= 0)
                    return true;
            }
            return false;
        }


        static readonly string[] SearchEngine = { "GOOGLE", "YAHOO", "MSN", "BAIDU", "SOGOU", "SOHU", "SINA", "163", "LYCOS", "TOM", "YISOU", "IASK", "SOSO", "GOUGOU", "ZHONGSOU" };

        /// <summary>
        /// 判断是否来自搜索引擎链接
        /// </summary>
        /// <returns>是否来自搜索引擎链接</returns>
        public static bool IsSearchEnginesGet(this HttpRequest request)
        {
            if (request.UrlReferrer == null)
                return false;
            string tmpReferrer = request.UrlReferrer.ToString().ToUpper();
            foreach (var s in SearchEngine)
            {
                if (tmpReferrer.IndexOf(s) >= 0)
                    return true;
            }
            return false;
        }

        /// <summary>
        /// 获得当前完整Url地址
        /// </summary>
        /// <returns>当前完整Url地址</returns>
        public static string GetUrl(this HttpRequest request)
        {
            return request.Url.ToString();
        }

        /// <summary>
        /// 获得当前完整Url地址
        /// </summary>
        /// <returns>当前完整Url地址</returns>
        public static string GetUrl()
        {
            if (HttpContext.Current != null)
                return HttpContext.Current.Request.GetUrl();
            return string.Empty;
        }

        /// <summary>
        /// 获得当前页面的名称
        /// </summary>
        /// <returns>当前页面的名称</returns>
        public static string GetPageName(this HttpRequest request)
        {
            string[] urlArr = request.Url.AbsolutePath.Split('/');
            return urlArr[urlArr.Length - 1].ToLower();
        }

        /// <summary>
        /// 返回表单或Url参数的总个数
        /// </summary>
        /// <returns></returns>
        public static int GetParamCount(this HttpRequest request)
        {
            return request.Form.Count + request.QueryString.Count;
        }
        #endregion

        #region GetString

        /// <summary>
        /// 获得指定表单参数的值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="strName">表单参数</param>
        /// <returns>表单参数的值</returns>
        public static string GetFormString(this HttpRequest request, string strName)
        {
            var qs = request.Form[strName];
            return string.IsNullOrWhiteSpace(qs) ? string.Empty : qs.Trim();
        }

        /// <summary>
        /// 获得指定Url参数的值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="strName">Url参数</param>
        /// <returns>Url参数的值</returns>
        public static string GetQueryString(this HttpRequest request, string strName)
        {
            var qs = request.QueryString[strName];
            return string.IsNullOrWhiteSpace(qs) ? string.Empty : qs.Trim();
        }

        /// <summary>
        /// 获得Url或表单参数的值, 先判断Url参数是否为空字符串, 如为True则返回表单参数的值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="strName">参数</param>
        /// <returns>Url或表单参数的值</returns>
        public static string GetString(this HttpRequest request, string strName)
        {
            var result = GetQueryString(request, strName);
            if (string.Empty.Equals(result))
                return GetFormString(request, strName);
            return result;
        }

        /// <summary>
        /// HttpContext.Current 
        /// </summary>
        /// <param name="strName"></param>
        /// <returns></returns>
        public static string GetString(string strName)
        {
            return HttpContext.Current.Request.GetString(strName);
        }

        /// <summary>
        /// 获取request的数据,并截取字符串
        /// </summary>
        /// <param name="strName"></param>
        /// <param name="takeLength"></param>
        /// <returns></returns>
        public static string GetString(string strName, int limit)
        {
            return HttpContext.Current.Request.GetString(strName).CutString(limit);
        }
        #endregion

        #region GetInt

        /// <summary>
        /// 获得指定Url参数的int类型值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="strName">Url参数</param>
        /// <param name="defValue">缺省值</param>
        /// <returns>Url参数的int类型值</returns>
        public static int GetQueryInt(this HttpRequest request, string strName, int defValue = 0)
        {
            return request.GetQueryString(strName).StrToInt(defValue);
        }

        /// <summary>
        /// 获得指定表单参数的int类型值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="strName">表单参数</param>
        /// <param name="defValue">缺省值</param>
        /// <returns>表单参数的int类型值</returns>
        public static int GetFormInt(this HttpRequest request, string strName, int defValue = 0)
        {
            return request.GetFormString(strName).StrToInt(defValue);
        }

        /// <summary>
        /// 获得指定Url或表单参数的int类型值, 先判断Url参数是否为缺省值, 如为True则返回表单参数的值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="strName">Url或表单参数</param>
        /// <param name="defValue">缺省值</param>
        /// <returns>Url或表单参数的int类型值</returns>
        public static int GetInt(this HttpRequest request, string strName, int defValue = 0)
        {
            var result = GetQueryInt(request, strName, defValue);
            if (result == defValue)
                return GetFormInt(request, strName, defValue);
            return result;
        }

        /// <summary>
        /// HttpContext.Current
        /// </summary>
        /// <param name="strName"></param>
        /// <param name="defValue"></param>
        /// <returns></returns>
        public static int GetInt(string strName, int defValue = 0)
        {
            return HttpContext.Current.Request.GetInt(strName, defValue);
        }
        #endregion

        #region GetInt64

        /// <summary>
        /// 获得指定Url参数的Int64类型值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="strName">Url参数</param>
        /// <param name="defValue">缺省值</param>
        /// <returns>Url参数的Int64类型值</returns>
        public static Int64 GetQueryInt64(this HttpRequest request, string strName, Int64 defValue = 0)
        {
            return request.GetQueryString(strName).StrToInt64(defValue);
        }

        /// <summary>
        /// 获得指定表单参数的Int64类型值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="strName">表单参数</param>
        /// <param name="defValue">缺省值</param>
        /// <returns>表单参数的Int64类型值</returns>
        public static Int64 GetFormInt64(this HttpRequest request, string strName, Int64 defValue = 0)
        {
            return request.GetFormString(strName).StrToInt64(defValue);
        }

        /// <summary>
        /// 获得指定Url或表单参数的Int64类型值, 先判断Url参数是否为缺省值, 如为True则返回表单参数的值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="strName">Url或表单参数</param>
        /// <param name="defValue">缺省值</param>
        /// <returns>Url或表单参数的Int64类型值</returns>
        public static Int64 GetInt64(this HttpRequest request, string strName, Int64 defValue = 0)
        {
            var result = GetQueryInt64(request, strName, defValue);
            if (result == defValue)
                return GetFormInt64(request, strName, defValue);
            return result;
        }

        /// <summary>
        /// HttpContext.Current
        /// </summary>
        /// <param name="strName"></param>
        /// <param name="defValue"></param>
        /// <returns></returns>
        public static Int64 GetInt64(string strName, Int64 defValue = 0)
        {
            return HttpContext.Current.Request.GetInt64(strName, defValue);
        }
        #endregion

        #region GetFloat

        /// <summary>
        /// 获得指定Url参数的float类型值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="strName">Url参数</param>
        /// <param name="defValue">缺省值</param>
        /// <returns>Url参数的int类型值</returns>
        public static float GetQueryFloat(this HttpRequest request, string strName, float defValue = 0)
        {
            return request.GetQueryString(strName).StrToFloat(defValue);
        }

        /// <summary>
        /// 获得指定表单参数的float类型值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="strName">表单参数</param>
        /// <param name="defValue">缺省值</param>
        /// <returns>表单参数的float类型值</returns>
        public static float GetFormFloat(this HttpRequest request, string strName, float defValue = 0)
        {
            return request.GetFormString(strName).StrToFloat(defValue);
        }

        /// <summary>
        /// 获得指定Url或表单参数的float类型值, 先判断Url参数是否为缺省值, 如为True则返回表单参数的值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="strName">Url或表单参数</param>
        /// <param name="defValue">缺省值</param>
        /// <returns>Url或表单参数的int类型值</returns>
        public static float GetFloat(this HttpRequest request, string strName, float defValue = 0)
        {
            return request.GetString(strName).StrToFloat(defValue);
        }

        /// <summary>
        /// HttpContext.Current
        /// </summary>
        /// <param name="strName"></param>
        /// <param name="defValue"></param>
        /// <returns></returns>
        public static float GetFloat(string strName, float defValue = 0)
        {
            return HttpContext.Current.Request.GetFloat(strName, defValue);
        }

        #endregion

        #region GetDateTime

        /// <summary>
        /// 获得指定Url参数的DateTime类型值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="strName">Url参数</param>
        /// <param name="defValue">缺省值</param>
        /// <returns>Url参数的int类型值</returns>
        public static DateTime GetQueryDateTime(this HttpRequest request, string strName, DateTime defValue)
        {
            return request.GetQueryString(strName).StrToDateTime(defValue);
        }

        /// <summary>
        /// 获得指定表单参数的DateTime类型值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="strName">表单参数</param>
        /// <param name="defValue">缺省值</param>
        /// <returns>表单参数的float类型值</returns>
        public static DateTime GetFormDateTime(this HttpRequest request, string strName, DateTime defValue)
        {
            return request.GetFormString(strName).StrToDateTime(defValue);
        }

        /// <summary>
        /// 获得指定Url或表单参数的DateTime类型值, 先判断Url参数是否为缺省值, 如为True则返回表单参数的值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="strName">Url或表单参数</param>
        /// <param name="defValue">缺省值</param>
        /// <returns>Url或表单参数的int类型值</returns>
        public static DateTime GetDateTime(this HttpRequest request, string strName, DateTime defValue)
        {
            var result = GetQueryDateTime(request, strName, defValue);
            if (result == defValue)
                return GetFormDateTime(request, strName, defValue);
            return result;
        }

        /// <summary>
        /// DateTime
        /// </summary>
        /// <param name="strName"></param>
        /// <param name="defValue"></param>
        /// <returns></returns>
        public static DateTime GetDateTime(string strName, DateTime defValue)
        {
            return HttpContext.Current.Request.GetDateTime(strName, defValue);
        }





        #endregion

        #region GetByte

        /// <summary>
        /// 获得指定Url参数的byte类型值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="strName">Url参数</param>
        /// <param name="defValue">缺省值</param>
        /// <returns>Url参数的int类型值</returns>
        public static byte GetQueryByte(this HttpRequest request, string strName, byte defValue = 0)
        {
            return request.GetQueryString(strName).StrToByte(defValue);
        }

        /// <summary>
        /// 获得指定表单参数的byte类型值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="strName">表单参数</param>
        /// <param name="defValue">缺省值</param>
        /// <returns>表单参数的float类型值</returns>
        public static byte GetFormByte(this HttpRequest request, string strName, byte defValue = 0)
        {
            return request.GetFormString(strName).StrToByte(defValue);
        }

        /// <summary>
        /// 获得指定Url或表单参数的GetByte类型值, 先判断Url参数是否为缺省值, 如为True则返回表单参数的值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="strName">Url或表单参数</param>
        /// <param name="defValue">缺省值</param>
        /// <returns>Url或表单参数的int类型值</returns>
        public static byte GetByte(this HttpRequest request, string strName, byte defValue = 0)
        {
            return request.GetString(strName).StrToByte(defValue);
        }

        /// <summary>
        /// 获得指定Url或表单参数的GetByte类型值
        /// </summary>
        /// <param name="strName"></param>
        /// <param name="defValue"></param>
        /// <returns></returns>
        public static byte GetByte(string strName, byte defValue = 0)
        {
            return HttpContext.Current.Request.GetByte(strName, defValue);
        }

        #endregion

        #region GetBoolean

        /// <summary>
        /// 获得指定Url参数的GetBool类型值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="strName">Url参数</param>
        /// <param name="defValue">缺省值</param>
        /// <returns>Url参数的bool类型值</returns>
        public static bool GetQueryBool(this HttpRequest request, string strName, bool defValue = false)
        {
            return request.GetQueryString(strName).StrToBoolean(defValue);
        }

        /// <summary>
        /// 获得指定表单参数的GetBool类型值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="strName">表单参数</param>
        /// <param name="defValue">缺省值</param>
        /// <returns>表单参数的bool类型值</returns>
        public static bool GetFormBool(this HttpRequest request, string strName, bool defValue = false)
        {
            return request.GetFormString(strName).StrToBoolean(defValue);
        }

        /// <summary>
        /// 获得指定Url或表单参数的GetBool类型值, 先判断Url参数是否为缺省值, 如为True则返回表单参数的值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="strName">Url或表单参数</param>
        /// <param name="defValue">缺省值</param>
        /// <returns>Url或表单参数的bool类型值</returns>
        public static bool GetBool(this HttpRequest request, string strName, bool defValue = false)
        {
            return request.GetString(strName).StrToBoolean(defValue);
        }

        /// <summary>
        /// 获得指定Url或表单参数的GetBool类型值
        /// </summary>
        /// <param name="strName"></param>
        /// <param name="defValue"></param>
        /// <returns></returns>
        public static bool GetBool(string strName, bool defValue = false)
        {
            return HttpContext.Current.Request.GetBool(strName, defValue);
        }

        #endregion

        #region ip地址
        /// <summary>
        /// 获得当前页面客户端的IP
        /// </summary>
        /// <returns>当前页面客户端的IP</returns>
        public static string GetIP(this HttpRequest request)
        {
            string result = request.ServerVariables["REMOTE_ADDR"];

            if (string.IsNullOrEmpty(result))
                result = request.ServerVariables["HTTP_X_FORWARDED_FOR"];

            if (string.IsNullOrEmpty(result))
                result = request.UserHostAddress;

            if (string.IsNullOrEmpty(result) || !CheckHelper.IsIP(result))
                return "127.0.0.1";

            return result;
        }

        /// <summary>
        /// 获得当前页面客户端的IP
        /// </summary>
        /// <returns></returns>
        public static string GetIP()
        {
            return HttpContext.Current.Request.GetIP();
        }
        /// <summary>
        /// IP地址转换为数字
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public static long GetIPToInt(this HttpRequest request)
        {
            IPAddress address;
            if (IPAddress.TryParse(request.GetIP(), out address))
            {
                byte[] addressBytes = address.GetAddressBytes();
                if (addressBytes.Length == 4)
                    return BitConverter.ToUInt32(addressBytes, 0);
                if (addressBytes.Length == 8)
                    return (long)BitConverter.ToUInt64(addressBytes, 0);
            }
            return 0;
        }

        /// <summary>
        /// IP地址转换为数字
        /// </summary>
        /// <returns></returns>
        public static long GetIPToInt()
        {
            return HttpContext.Current.Request.GetIPToInt();
        }
        #endregion

        #region 读取cookie

        /// <summary>
        /// 读cookie值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="strName">名称</param>
        /// <returns>cookie值</returns>
        public static string GetCookie(this HttpRequest request, string strName)
        {
            var cookieCollection = request.Cookies;
            if (cookieCollection != null)
            {
                HttpCookie cookie = cookieCollection[strName];
                if (cookie != null)
                {
                    return cookie.Value;
                }
            }
            return string.Empty;
        }

        /// <summary>
        /// 读cookie值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="strName">名称</param>
        /// <param name="key"></param>
        /// <returns>cookie值</returns>
        public static string GetCookie(this HttpRequest request, string strName, string key)
        {
            var cookieCollection = request.Cookies;
            HttpCookie cookie = cookieCollection[strName];
            if (cookie != null)
            {
                var cok = cookie[key];
                if (!string.IsNullOrWhiteSpace(cok))
                {
                    return cok;
                }
            }
            return string.Empty;
        }
        #endregion

        #region Get Client Brower Info and OS Info
        private static readonly string[] BrowerNames = { "MSIE", "Firefox", "Opera", "Netscape", "Safari", "Lynx", "Konqueror", "Mozilla" };
        //private const string[] osNames = { "Win", "Mac", "Linux", "FreeBSD", "SunOS", "OS/2", "AIX", "Bot", "Crawl", "Spider" };

        /// <summary>
        /// 获得浏览器信息
        /// </summary>
        /// <returns></returns>
        public static string GetClientBrower(this HttpRequest request)
        {
            string agent = request.ServerVariables["HTTP_USER_AGENT"];
            if (!string.IsNullOrEmpty(agent))
            {
                foreach (string name in BrowerNames)
                {
                    if (agent.Contains(name))
                        return name;
                }
            }
            return "Other";
        }

        /// <summary>
        /// 获得操作系统信息
        /// </summary>
        /// <returns></returns>
        public static string GetClientOs(this HttpRequest request)
        {
            string os;
            string agent = request.ServerVariables["HTTP_USER_AGENT"];
            if (agent == null)
                return "Other";

            if (agent.IndexOf("Win") > -1)
                os = "Windows";
            else if (agent.IndexOf("Mac") > -1)
                os = "Mac";
            else if (agent.IndexOf("Linux") > -1)
                os = "Linux";
            else if (agent.IndexOf("FreeBSD") > -1)
                os = "FreeBSD";
            else if (agent.IndexOf("SunOS") > -1)
                os = "SunOS";
            else if (agent.IndexOf("OS/2") > -1)
                os = "OS/2";
            else if (agent.IndexOf("AIX") > -1)
                os = "AIX";
            else if (Regex.IsMatch(agent, @"(Bot|Crawl|Spider)"))
                os = "Spiders";
            else
                os = "Other";
            return os;
        }
        #endregion

        #region 从Request里面获取对应的对象
        /// <summary>
        /// 从Request里面获取对应的对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T GetEntity<T>(this HttpRequest request) where T : new()
        {
            PropertyInfo[] pis = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public);
            T t = new T();
            foreach (PropertyInfo pi in pis)
            {
                var result = request[pi.Name];
                if (result != null)
                {
                    DynamicMethodCompiler.CreateSetHandler(pi)(t, result);
                }
            }
            return t;
        }

        /// <summary>
        /// 从HttpRequestBase里面获取对应的对象(MVC)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="request"></param>
        /// <returns></returns>
        public static T GetEntity<T>(this HttpRequestBase request) where T : new()
        {
            PropertyInfo[] pis = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public);
            T t = new T();
            foreach (PropertyInfo pi in pis)
            {
                var result = request[pi.Name];
                if (result != null)
                {
                    DynamicMethodCompiler.CreateSetHandler(pi)(t, result);
                }
            }
            return t;
        }
        #endregion
    }
}
